/**
 * See the definition of `@types/lodash`.
 */
type GetIndexedField<T, K> = K extends keyof T
  ? T[K]
  : K extends `${number}`
  ? 'length' extends keyof T
  ? number extends T['length']
  ? number extends keyof T
  ? T[number]
  : undefined
  : undefined
  : undefined
  : undefined;

type FieldWithPossiblyUndefined<T, Key> =
  | Get<Exclude<T, undefined>, Key>
  | Extract<T, undefined>;

type IndexedFieldWithPossiblyUndefined<T, Key> =
  | GetIndexedField<Exclude<T, undefined>, Key>
  | Extract<T, undefined>;

export type Get<T, P> = P extends `${infer Left}.${infer Right}`
  ? Left extends keyof Exclude<T, undefined>
  ? FieldWithPossiblyUndefined<Exclude<T, undefined>[Left], Right> | Extract<T, undefined>
  : Left extends `${infer FieldKey}[${infer IndexKey}]`
  ? FieldKey extends keyof T
  ? FieldWithPossiblyUndefined<IndexedFieldWithPossiblyUndefined<T[FieldKey], IndexKey>, Right>
  : undefined
  : undefined
  : P extends keyof T
  ? T[P]
  : P extends `${infer FieldKey}[${infer IndexKey}]`
  ? FieldKey extends keyof T
  ? IndexedFieldWithPossiblyUndefined<T[FieldKey], IndexKey>
  : undefined
  : IndexedFieldWithPossiblyUndefined<T, P>;